/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse;

import java.sql.*;
import java.util.*; //import java.util.Calendar;
//import java.util.GregorianCalendar;
import java.security.*;

import nfse.query.QueryDate;
import nfse.result.DatabaseResultEntry;
import nfse.dataset.netflow.NetFlowThread;
import nfse.gui.config.SoleraConfig;

/*******************************************************************************
 * Convinience class for obtaining system metadata information.
 * 
 * @author This code is the property of Los Alamos National Laboratory and the
 *         University of California, Copyright 2005
 */
public class MetaDatabase extends nfse.JDBCDatabase {

	public static MetaDatabase create() throws Exception {
		Properties props = new Properties();
		props.setProperty("user", NetFSE.METADATA_USER);
		props.setProperty("password", NetFSE.METADATA_PASSWORD);
		props.setProperty("client_encoding", "UTF8");

		Class.forName("org.postgresql.Driver");
		String url = "jdbc:postgresql://" + NetFSE.METADATA_HOST + "/"
				+ NetFSE.METADATA_DATABASE;

		MetaDatabase mdb = new MetaDatabase(url, props);
		return mdb;
	}

	public MetaDatabase(String dbUrl, Properties props) throws Exception {
		super(dbUrl, props);
	}

	public void addDataFile(long fileID, int sensorID, int nodeID, String path) {
		try {
			Statement s = createStatement();
			String sql = "insert into data_files values ("+fileID+","
					+ sensorID + "," + nodeID + ",0,0,'" + path + "','')";
			s.execute(sql);
			
			Vector apps = new Vector();
			sql = "select * from App_List";
			ResultSet rs = s.executeQuery(sql);
			while (rs.next()) {
				apps.addElement(rs.getInt("App_ID"));
			}
			rs.close();
			for (int i = 0; i < apps.size(); i++) {
				s.execute("insert into data_files_by_app values (" +fileID + "," + (Integer)apps.elementAt(i) + ",0,0)" );
			}
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public SyslogThread[] getSyslogThreads() {
		SyslogThread[] threads = null;
		try {
			Vector temp = new Vector();
			String sql = "select * from syslog_agent_conf";
			Statement s = createStatement();
			ResultSet rs = s.executeQuery(sql);
			while (rs.next()) {
				int sensor = rs.getInt("sensor");
				String ip = rs.getString("ip");
				if (ip == null)
					ip = "";
				String filePath = rs.getString("file_path");
				String keyword = rs.getString("keyword");
				SyslogThread st = new SyslogThread(sensor, filePath, keyword,
						ip);
				temp.addElement(st);
			}
			rs.close();
			s.close();
			threads = new SyslogThread[temp.size()];
			for (int i = 0; i < threads.length; i++) {
				threads[i] = (SyslogThread) temp.elementAt(i);
			}
			return threads;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return threads;
	}

	public SyslogThread getSyslogThread(int sensorID) {
		SyslogThread thread = null;
		try {

			String sql = "select * from syslog_agent_conf where sensor="
					+ sensorID;
			Statement s = createStatement();
			ResultSet rs = s.executeQuery(sql);
			if (rs.next()) {
				int sensor = rs.getInt("sensor");
				String ip = rs.getString("ip");
				if (ip == null)
					ip = "";
				String filePath = rs.getString("file_path");
				String keyword = rs.getString("keyword");
				thread = new SyslogThread(sensor, filePath, keyword, ip);

			}
			rs.close();
			s.close();

			return thread;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public NetFlowThread[] getNetFlowThreads() {
		NetFlowThread[] threads = null;
		try {
			Vector temp = new Vector();
			String sql = "select * from netflow_agent_conf";
			Statement s = createStatement();
			ResultSet rs = s.executeQuery(sql);
			while (rs.next()) {
				int sensor = rs.getInt("sensor");
				int port = rs.getInt("port");
				NetFlowThread st = new NetFlowThread(sensor, port);
				temp.addElement(st);
			}
			rs.close();
			s.close();
			threads = new NetFlowThread[temp.size()];
			for (int i = 0; i < threads.length; i++) {
				threads[i] = (NetFlowThread) temp.elementAt(i);
			}
			return threads;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return threads;
	}

	/***************************************************************************
	 * Returns the distinct run numbers for a given date range and sensor.
	 * 
	 * @param startDate
	 *            The lower bound of the date range to query
	 * @param endDate
	 *            The uppper bound of the date range to query
	 * @param sensor
	 *            The sensor for which to obtain run information
	 * @return An array of integers representing the unique run numbers for the
	 *         date range
	 */
	public int[] getDistinctRuns(QueryDate startDate, QueryDate endDate, int sensor) {
		int[] result = new int[0];
		try {
			Vector temp = new Vector();
			Statement s = this.createStatement();
			String sql = "";
			if (endDate != null) {
				sql = "select distinct Run from Static_Indices where Sensor_ID="
						+ sensor
						+ " and Index_Date between '"
						+ startDate.toMySQLString()
						+ "' and '"
						+ endDate.toMySQLString() + "' order by Run asc";
			} else {
				sql = "select distinct Run from Static_Indices where Sensor_ID="
						+ sensor
						+ " and Index_Date='"
						+ startDate.toMySQLString() + "' order by Run asc";
			}

			System.out.println(sql);
			ResultSet rs = s.executeQuery(sql);
			if (rs != null) {
				while (rs.next()) {
					temp.addElement(new Integer(rs.getInt("Run")));
				}
				rs.close();
			}

			s.close();
			result = new int[temp.size()];
			for (int i = 0; i < result.length; i++) {
				result[i] = ((Integer) temp.elementAt(i)).intValue();
			}
		} catch (Exception E) {
			E.printStackTrace();
		}
		return result;
	}

	/***************************************************************************
	 * Returns an array of Run objects for a given time range and sensor. Used
	 * to determine what index structures to search for a time period for a
	 * particular sensor.
	 * 
	 * @param startDate
	 *            The lower bound of the date range to query
	 * @param endDate
	 *            The uppper bound of the date range to query
	 * @param sensor
	 *            The sensor for which to obtain run information
	 * @return An array of Run objects indicating the indexes to search for this
	 *         time period
	 */
	public Run[] getRuns(QueryDate startDate, QueryDate endDate, int sensor) {
		Run[] result = new Run[0];
		try {
			if (endDate == null)
				endDate = startDate;
			Vector temp = new Vector();
			Statement s = this.createStatement();
			String sql = "select * from Static_Indices where Sensor_ID="
					+ sensor + " and (Min_Time >= " + startDate.startTS / 1000
					+ " and Max_Time <=" + endDate.endTS / 1000 + ")"
					+ " group by Month, Day, Year, Run";
			ResultSet rs = s.executeQuery(sql);
			if (rs != null) {
				while (rs.next()) {
					Run run = new Run();
					run.setRun(rs.getInt("Run"));
					run.setMinTime(rs.getLong("Min_Time"));
					run.setMaxTime(rs.getLong("Max_Time"));
					run.setMonth(rs.getInt("Month"));
					run.setDay(rs.getInt("Day"));
					run.setYear(rs.getInt("Year"));
					run.setDate(nfse.query.QueryDate.processDate(rs
							.getString("Index_Date")));
					temp.addElement(run);
				}
				rs.close();
			}
			s.close();
			result = new Run[temp.size()];
			for (int i = 0; i < result.length; i++) {
				result[i] = (Run) temp.elementAt(i);
			}
		} catch (Exception E) {
			E.printStackTrace();
		}
		return result;
	}

	/***************************************************************************
	 * Returns an array of Run objects for a given time range and sensor. Used
	 * to determine what index structures to search for a time period for a
	 * particular sensor.
	 * 
	 * @param startTS
	 *            The lower bound of the date range to query
	 * @param endTS
	 *            The uppper bound of the date range to query
	 * @param sensor
	 *            The sensor for which to obtain run information
	 * @return An array of Run objects indicating the indexes to search for this
	 *         time period
	 */
	public Run[] getRuns(java.sql.Timestamp startTS, java.sql.Timestamp endTS,
			int sensor) {
		Run[] result = new Run[0];
		try {
			Vector temp = new Vector();
			Statement s = this.createStatement();
			String sql = "select * from Static_Indices where Field_ID=1 and Sensor_ID="
					+ sensor
					+ " and ((Min_Time between  "
					+ startTS.getTime()
					/ 1000
					+ " and "
					+ endTS.getTime()
					/ 1000
					+ ") or (Max_Time between "
					+ startTS.getTime()
					/ 1000
					+ " and "
					+ endTS.getTime()
					/ 1000
					+ ") or (Min_Time <= "
					+ startTS.getTime()
					/ 1000
					+ " and Max_Time >= "
					+ endTS.getTime() / 1000 + "))" + " ";
			// System.out.println(sql);
			ResultSet rs = s.executeQuery(sql);
			if (rs != null) {
				while (rs.next()) {
					Run run = new Run();
					run.setRun(rs.getInt("Run"));
					run.setMinTime(rs.getLong("Min_Time"));
					run.setMaxTime(rs.getLong("Max_Time"));
					run.setMonth(rs.getInt("Month"));
					run.setDay(rs.getInt("Day"));
					run.setYear(rs.getInt("Year"));
					run.setDate(nfse.query.QueryDate.processDate(rs
							.getString("Index_Date")));
					temp.addElement(run);
				}
				rs.close();
			}

			s.close();
			result = new Run[temp.size()];
			for (int i = 0; i < result.length; i++) {
				result[i] = (Run) temp.elementAt(i);
			}
		} catch (Exception E) {
			E.printStackTrace();
		}
		return result;
	}

	public TempTableRun[] getTempTableRuns(java.sql.Timestamp startTS,
			java.sql.Timestamp endTS, int sensor) {
		TempTableRun[] result = new TempTableRun[0];
		try {
			Vector temp = new Vector();
			Statement s = this.createStatement();
			String sql = "select * from Temp_Tables a, Nodes b where a.Node_ID=b.ID and a.Sensor_ID="
					+ sensor
					+ " and ( "
					+ "  (Min_TS between  '"
					+ startTS.toString()
					+ "' and '"
					+ endTS.toString()
					+ "') "
					+ " or (Max_TS between '"
					+ startTS.toString()
					+ "' and '"
					+ endTS.toString()
					+ "') "
					+ " or (Min_TS <= '"
					+ startTS.toString()
					+ "' and Max_TS >= '"
					+ endTS.toString() + "') or (Min_TS is null) " + ") ";
			System.out.println(sql);

			ResultSet rs = s.executeQuery(sql);
			if (rs != null) {
				while (rs.next()) {
					TempTableRun run = new TempTableRun();
					run.setNodeID(rs.getInt("Node_ID"));
					run.setHost(rs.getString("Name"));
					run.setTable(rs.getString("Table_Name"));
					run.setMinTS(rs.getTimestamp("Min_TS"));
					run.setMaxTS(rs.getTimestamp("Max_TS"));
					run.setDynamicUser(rs.getString("Dynamic_DB_User"));
					run.setDynamicPassword(rs.getString("Dynamic_DB_Password"));
					run.setSensorID(sensor);
					temp.addElement(run);
				}
				rs.close();
			}

			s.close();
			result = new TempTableRun[temp.size()];
			for (int i = 0; i < result.length; i++) {
				result[i] = (TempTableRun) temp.elementAt(i);
			}
		} catch (Exception E) {
			E.printStackTrace();
		}
		return result;
	}

	/***************************************************************************
	 * This method tries to authenticate the given user/password combination,
	 * returning the user identifier from the system metadata upon success.
	 * 
	 * @param user
	 *            The user name from the system metadata
	 * @param pass
	 *            The password for this user
	 * @return The user identifier from the system metadata on success or -1 if
	 *         authentication fails
	 */
	public int authenticate(String user, String pass) {
		try {

			Statement s = this.createStatement();
			String sql = "select * from Users where User_Name='" + user + "'";
			ResultSet rs = s.executeQuery(sql);
			if (!rs.next()) {
				rs.close();
				s.close();
				return -1; // There was no matching user name
			}

			// Computed the hashed value of the pass parameter
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.digest(pass.getBytes());
			byte[] digest = md.digest(); // Compute the digest
			StringBuffer temp = new StringBuffer();
			for (int i = 0; i < digest.length; i++)
				temp.append(Integer.toHexString(digest[i]));
			String digestStr = temp.toString();

			// Compare the two passwords
			String password = rs.getString("Password");
			if (password.compareTo(digestStr) == 0) {
				int userID = rs.getInt("ID");
				rs.close();
				s.close();
				return userID; // Return the user ID, success
			}
			rs.close();
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
		return -1; // Failed to authenticate
	}

	/***************************************************************************
	 * Helper method for returning IndexInfo for arbitrary SQL. Used in several
	 * public methods below.
	 * 
	 * @param sql
	 * @return An arry of IndexInfo objects of length 0 or more
	 */
	private IndexInfo[] staticIndexInfo(String sql) {
		IndexInfo[] result = null;
		try {
			Statement s = connection.createStatement();
			ResultSet rs = s.executeQuery(sql);
			Vector temp = new Vector();
			while (rs.next()) {
				IndexInfo info = new IndexInfo();
				info.setSensorId(rs.getInt("Sensor_ID"));
				info.setMonth(rs.getInt("Month"));
				info.setDay(rs.getInt("Day"));
				info.setYear(rs.getInt("Year"));
				info.setRun(rs.getInt("Run"));
				info.setField(rs.getInt("Field_ID"));
				info.setDbPath(rs.getString("DB_Path"));
				info.setMaxTime(rs.getLong("Max_Time"));
				info.setMinTime(rs.getLong("Min_Time"));
				temp.addElement(info);
			}
			rs.close();
			s.close();
			result = new IndexInfo[temp.size()];
			for (int i = 0; i < result.length; i++) {
				result[i] = (IndexInfo) temp.elementAt(i);
			}
		} catch (Exception E) {
			E.printStackTrace();
		}
		return result;
	}

	/***************************************************************************
	 * Finds static index information matching the criteria specifed in the
	 * parameters or null if there is no match.
	 * 
	 * @param month
	 *            Month of the index (1-12)
	 * @param day
	 *            Day of month of the index (1-31)
	 * @param year
	 *            Year of the index (YYYY)
	 * @param run
	 *            Run of the index (1-n)
	 * @param field
	 *            Field identifier of the index
	 * @param sensor
	 *            Sensor identifier of the index
	 * @return IndexInfo matching the parameters or null if none could be found
	 */
	public IndexInfo getStaticIndexInfo(int month, int day, int year, int run,
			int field, int sensor) {
		String sql = "select * from Static_Indices where Month=" + month
				+ " and Day=" + day + " and Year=" + year + " and Run=" + run
				+ " and Field_ID=" + field + " and Sensor_ID=" + sensor;

		return (staticIndexInfo(sql))[0];
	}

	/***************************************************************************
	 * Finds dynamic index information matching the criteria specifed in the
	 * parameters or null if there is no match.
	 * 
	 * @param month
	 *            Month of the index (1-12)
	 * @param day
	 *            Day of month of the index (1-31)
	 * @param year
	 *            Year of the index (YYYY)
	 * @param run
	 *            Run of the index (1-n)
	 * @param field
	 *            Field identifier of the index
	 * @param sensor
	 *            Sensor identifier of the index
	 * @return IndexInfo matching the parameters or null if none could be found
	 */
	public IndexInfo getLocalIndexInfo(int node, int month, int day, int year,
			int run, int field, int sensor) {
		IndexInfo info = null;
		try {
			Statement s = connection.createStatement();
			String sql = "select * from Local_Indices where Month=" + month
					+ " and Day=" + day + " and Year=" + year + " and Run="
					+ run + " and Field_ID=" + field + " and Sensor_ID="
					+ sensor + " and Node_ID=" + node;

			ResultSet rs = s.executeQuery(sql);
			if (rs.next()) {
				info = new IndexInfo();
				info.setSensorId(rs.getInt("Sensor_ID"));
				info.setMonth(month);
				info.setDay(day);
				info.setYear(year);
				info.setRun(run);
				info.setField(field);
				info.setDataPath(rs.getString("Data_Path"));
				info.setDbPath(rs.getString("DB_Path"));
				info.setMaxTime(rs.getLong("Max_Time"));
				info.setMinTime(rs.getLong("Min_Time"));
			}
			rs.close();
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
		return info;
	}

	/***************************************************************************
	 * Finds data file information matching the criteria specifed in the
	 * parameters or null if there is no match.
	 * 
	 * @param month
	 *            Month of the index (1-12)
	 * @param day
	 *            Day of month of the index (1-31)
	 * @param year
	 *            Year of the index (YYYY)
	 * @param run
	 *            Run of the index (1-n)
	 * @param sensor
	 *            Sensor identifier of the index
	 * @return A DataInfo object matching the parameters or null if none could
	 *         be found
	 */
	public DataInfo getDataInfo(int month, int day, int year, int run,
			int sensor) {
		DataInfo info = null;
		try {
			Statement s = connection.createStatement();
			String sql = "select * from Data_Info where Month=" + month
					+ " and Day=" + day + " and Year=" + year + " and Run="
					+ run + " and Sensor_ID=" + sensor;

			ResultSet rs = s.executeQuery(sql);
			if (rs.next()) {
				info = new DataInfo();
				info.setSensor(sensor);
				info.setMonth(month);
				info.setDay(day);
				info.setYear(year);
				info.setRun(run);
				info.setDataPath(rs.getString("Path"));
				info.setMaxTime(rs.getLong("Max_Time"));
				info.setMinTime(rs.getLong("Min_Time"));
				info.setNumRecords(rs.getLong("Num_Lines"));
				info.setNumBytes(rs.getLong("Num_Bytes"));
				rs.close();
				s.close();
				return info;
			}
			rs.close();
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
		return null;
	}

	/***************************************************************************
	 * Creates an entry in the system metadata for a dynamic index according to
	 * the IndexInfo parameter.
	 * 
	 * @param indexInfo
	 *            The index information of the dynamic index being added
	 */
	public void addLocalIndex(IndexInfo indexInfo) {
		try {
			Statement s = connection.createStatement();
			String sql = "insert into Local_Indices values (" + indexInfo.getNodeId()
					+ ", " + indexInfo.getSensorId() + ", " + indexInfo.getField() + ", '"
					+ indexInfo.getYear() + "-" + indexInfo.getMonth() + "-"
					+ indexInfo.getDay() + "', " + indexInfo.getRun() + ", "
					+ indexInfo.getMonth() + ", " + indexInfo.getDay() + ", "
					+ indexInfo.getYear() + ", '" + indexInfo.getDbPath() + "', '"
					+ indexInfo.getDataPath() + "', " + indexInfo.getMinTime() + ", "
					+ indexInfo.getMaxTime() + ")";
			s.execute(sql);
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	public void addTempTable(String tableName, int node, int sensor) {
		try {
			Statement s = connection.createStatement();
			String sql = "insert into Temp_Tables values (" + node + ", "
					+ sensor + ", '" + tableName + "',null,null)";
			// System.out.println(sql);
			s.execute(sql);
			s.close();

		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	public void removeTempTable(String tableName) {
		try {
			Statement s = connection.createStatement();
			String sql = "delete from Temp_Tables where Table_Name='"
					+ tableName + "'";

			s.execute(sql);
			s.close();

		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	public void setTempTableTimestamps(String tableName,
			java.sql.Timestamp minTS, java.sql.Timestamp maxTS) {
		try {
			Statement s = connection.createStatement();
			String sql = "update Temp_Tables set Min_TS='" + minTS.toString()
					+ "', Max_TS='" + maxTS.toString() + "' where Table_Name='"
					+ tableName + "'";
			s.execute(sql);
			s.close();

		} catch (Exception E) {
			E.printStackTrace();
		}

	}

	public long getRecordCount(String date) {
		try {
			long count = 0;
			Statement s = connection.createStatement();
			String sql = "select * from Daily_Record_Counts where Entry_Date='"
					+ date + "'";
			ResultSet rs = s.executeQuery(sql);
			if (rs.next()) {
				count = rs.getLong("Records_Processed");
			}
			rs.close();
			s.close();
			if (count < 0)
				count = 0;
			return count;
		} catch (Exception E) {
			E.printStackTrace();
		}
		return 0;
	}

	public long getExceededCount(String date) {
		try {
			long count = 0;
			Statement s = connection.createStatement();
			String sql = "select * from Daily_Record_Counts where Entry_Date='"
					+ date + "'";
			ResultSet rs = s.executeQuery(sql);
			if (rs.next()) {
				count = rs.getLong("Records_Over");
			}
			rs.close();
			s.close();
			if (count < 0)
				count = 0;
			return count;
		} catch (Exception E) {
			E.printStackTrace();
		}
		return 0;
	}

	public void updateRecordCounts(String date, long recordCount,
			long exceededCount, java.sql.Timestamp exceededTS) {
		try {
			Statement s = connection.createStatement();

			// Try to bring the table up-to-date for version 1.1
			try {
				String sql = "alter table Daily_Record_Counts add column Threshold_TS timestamp";
				s.execute(sql);
			} catch (Exception e) {

			}

			try {
				// Try to insert first, if there is an entry this will fail and
				// force an update
				String tsSQL = "'" + exceededTS + "'";
				if (exceededTS == null)
					tsSQL = "null";

				String sql = "insert into Daily_Record_Counts values ('" + date
						+ "'," + recordCount + ", " + exceededCount + ","
						+ tsSQL + ")";
				s.execute(sql);
			} catch (Exception e) {
				String tsSQL = "";
				if (exceededTS != null)
					tsSQL = ", Threshold_TS='" + exceededTS + "' ";

				// If the insert fails it indicates that a record exists (so
				// this is an update).
				String sql = "update Daily_Record_Counts set Records_Processed="
						+ recordCount
						+ ", Records_Over="
						+ exceededCount
						+ " "
						+ tsSQL + " where Entry_Date='" + date + "'";
				s.execute(sql);
			}
			s.close();

		} catch (Exception E) {
			E.printStackTrace();
		}

	}

	/***************************************************************************
	 * Creates an entry in the system metadata for a data file according to the
	 * DataInfo parameter.
	 * 
	 * @param indexInfo
	 *            Information about the data file being added
	 */
	public void addData(DataInfo info) {
		try {
			Statement s = connection.createStatement();
			String sql = "insert into Data_Info values (" + info.getSensor() + ", "
					+ 1 + ", '" + info.getYear() + "-" + info.getMonth() + "-" + info.getDay()
					+ "', " + info.getMonth() + ", " + info.getDay() + ", " + info.getYear()
					+ ", " + info.getRun() + ", '" + info.getDataPath() + "', "
					+ info.getNumBytes() + ", " + info.getNumRecords() + ", "
					+ info.getMinTime() + ", " + info.getMaxTime() + ",null,null)";
			s.execute(sql);
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	/***************************************************************************
	 * Removes a data file entry from the system metadata according to the given
	 * parameters.
	 * 
	 * @param month
	 *            Month of the index (1-12)
	 * @param day
	 *            Day of month of the index (1-31)
	 * @param year
	 *            Year of the index (YYYY)
	 * @param run
	 *            Run of the index (1-n)
	 * @param sensor
	 *            Sensor identifier of the index
	 */
	public void removeData(int month, int day, int year, int run, int sensor) {
		try {
			Statement s = connection.createStatement();
			String sql = "delete from Data_Info where " + "Sensor_ID=" + sensor
					+ " and " + "Run=" + run + " and " + "Index_Date='" + year
					+ "-" + month + "-" + day + "'";
			s.execute(sql);
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	/***************************************************************************
	 * Adds a static index entry to the system metadata according to the
	 * attributes of the IndexInfo parameter.
	 * 
	 * @param indexInfo
	 *            Information to add to the system metadata
	 */
	public void addStaticIndex(IndexInfo indexInfo) {
		try {
			Statement s = connection.createStatement();
			String sql = "insert into Static_Indices values ("
					+ indexInfo.getSensorId() + ", " + indexInfo.getField() + ", "
					+ indexInfo.getRun() + ", '" + indexInfo.getYear() + "-"
					+ indexInfo.getMonth() + "-" + indexInfo.getDay() + "', "
					+ indexInfo.getMonth() + ", " + indexInfo.getDay() + ", "
					+ indexInfo.getYear() + ", '" + indexInfo.getDbPath() + "', "
					+ indexInfo.getMinTime() + ", " + indexInfo.getMaxTime() + ")";
			s.execute(sql);
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	/***************************************************************************
	 * Removes a static index entry from the system metadata according to the
	 * given parameters.
	 * 
	 * @param nodeID
	 *            Node identifier of where this index resides
	 * @param sensor
	 *            Sensor identifier of the index
	 * @param month
	 *            Month of the index (1-12)
	 * @param day
	 *            Day of month of the index (1-31)
	 * @param year
	 *            Year of the index (YYYY)
	 * @param run
	 *            Run of the index (1-n)
	 */
	public void removeStaticIndex(int sensor, int field, int month, int day,
			int year, int run) {
		try {
			Statement s = connection.createStatement();
			String sql = "delete from Static_Indices where Sensor_ID=" + sensor
					+ " and Field_ID=" + field + " and " + "Run=" + run
					+ " and " + "Index_Date='" + year + "-" + month + "-" + day
					+ "'";
			s.execute(sql);
			s.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

}